﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace nRFProgramTool
{
    public partial class Form_nRFTool : Form
    {
        [DllImport("user32.dll")]
        public static extern int MessageBeep(uint uType);
        uint beep = 0x00000040;

        //发出不同类型的声音的参数如下：  
        //Ok = 0x00000000,  
        //Error = 0x00000010,  
        //Question = 0x00000020,  
        //Warning = 0x00000030,  
        //Information = 0x00000040  

        FlagClass flagc = new FlagClass();
        int programSucessNum = 0;

        public Form_nRFTool()
        {
            InitializeComponent();
        }

        private void button_openFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "固件文件|*.hex";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                string path = ofd.FileName;
                textBox_fileName.Text = path;
            }
            else
            {
                MessageBox.Show("未打开文件");
            }
        }

        private void button_eraseall_Click(object sender, EventArgs e)
        {
            label_autoResult.Text = "擦除中。。。";
            CmdReturnStr outStr = processCmd("nrfjprog --eraseall" + DefinedParam.clockspeed);
            if (outStr.error.Length == 0)
            {
                label_autoResult.Text = "擦除成功";
                Console.Beep(1600, 600);
            }
            else
            {
                textBox_outLog.AppendText(outStr.output + outStr.error);
                Console.Beep(1800, 3000);
            }
        }

        private void button_program_Click(object sender, EventArgs e)
        {
            if (File.Exists(textBox_fileName.Text) == true)
            {
                label_autoResult.Text = "烧录中。。。";
                Thread.Sleep(10);
                String tempCmdString = "nrfjprog --program " + textBox_fileName.Text + " --verify" + DefinedParam.clockspeed;
                CmdReturnStr outStr = processCmd(tempCmdString);
                if (outStr.error.Length == 0)
                {
                    tempCmdString = "nrfjprog --rbp all" + DefinedParam.clockspeed;
                    outStr = processCmd(tempCmdString);
                    if (outStr.error.Length == 0)
                    {
                        tempCmdString = "nrfjprog --reset" + DefinedParam.clockspeed;
                        outStr = processCmd(tempCmdString);
                        if (outStr.error.Length == 0)
                        {
                            label_autoResult.Text = "烧录成功";
                        }
                        else
                        {
                            label_autoResult.Text = "错误";
                            textBox_outLog.AppendText("错误指令：" + tempCmdString);
                            textBox_outLog.AppendText(outStr.error);
                        }
                    }
                    else
                    {
                        label_autoResult.Text = "错误";
                        textBox_outLog.AppendText("错误指令：" + tempCmdString);
                        textBox_outLog.AppendText(outStr.error);
                    }
                }
                else
                {
                    label_autoResult.Text = "错误:";
                    textBox_outLog.AppendText("错误指令：" + tempCmdString);
                    textBox_outLog.AppendText(outStr.error);
                }
            }
            else
            {
                MessageBox.Show(textBox_fileName.Text + "文件不存在");
            }
        }

        private void button_protec_Click(object sender, EventArgs e)
        {
            textBox_outLog.AppendText("读保护。。。");
            CmdReturnStr outStr = processCmd("nrfjprog --rbp all" + DefinedParam.clockspeed);
            textBox_outLog.AppendText(outStr.output + outStr.error);
        }

        private CmdReturnStr processCmd(string cmd)
        {
            CmdReturnStr cmdReturnStr = new CmdReturnStr();
            Process p = new Process();
            //设置要启动的应用程序
            p.StartInfo.FileName = "cmd.exe";
            //是否使用操作系统shell启动
            p.StartInfo.UseShellExecute = false;
            // 接受来自调用程序的输入信息
            p.StartInfo.RedirectStandardInput = true;
            //输出信息
            p.StartInfo.RedirectStandardOutput = true;
            // 输出错误
            p.StartInfo.RedirectStandardError = true;
            //不显示程序窗口
            p.StartInfo.CreateNoWindow = true;
            //启动程序
            p.Start();

            //向cmd窗口发送输入信息
            p.StandardInput.WriteLine(cmd);
            p.StandardInput.WriteLine("exit");

            p.StandardInput.AutoFlush = true;

            //获取输出信息
            cmdReturnStr.output = p.StandardOutput.ReadToEnd();
            cmdReturnStr.error = p.StandardError.ReadToEnd();
            //等待程序执行完退出进程
            p.WaitForExit();
            p.Close();

            return cmdReturnStr;
        }

        private void checkBox_aotu_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_aotu.Checked == true)
            {
                button_eraseall.Enabled = false;
                button_program.Enabled = false;
                button_protec.Enabled = false;
                if (flagc.get() == 0)
                {
                    Thread thread_aotu = new Thread(auto_Program_Verify_Protec);
                    flagc.set(1);
                    thread_aotu.Start();
                }
            }
            else
            {
                flagc.set(0);
                while (flagc.get() != 0) Thread.Sleep(100);
                button_eraseall.Enabled = true;
                button_program.Enabled = true;
                button_protec.Enabled = true;
            }
        }

        private void auto_Program_Verify_Protec()
        {
            bool flagFileNotExists = true;
            bool tempFlag = false;
            FlagClass flagc = new FlagClass();
            string tempstring;

            try
            {
                while (flagc.get() != 0 && flagFileNotExists)
                {
                    this.Invoke((EventHandler)(delegate { label_autoResult.Text = "读取设备ID。。。"; }));
                    CmdReturnStr outStr = processCmd("nrfjprog --memrd 0x10000060 --n 8" + DefinedParam.clockspeed);
                    if (outStr.error.Length > 0)
                    {
                        this.Invoke((EventHandler)(delegate { textBox_outLog.AppendText(outStr.error); }));
                        this.Invoke((EventHandler)(delegate { label_autoResult.Text = "未读取到设备"; }));
                    }
                    else
                    {
                        int i = outStr.output.IndexOf("0x10000060: ");
                        if (i > 0)
                        {
                            tempstring = outStr.output.Substring(i + "0x10000060: ".Length, 33);
                            this.Invoke((EventHandler)(delegate { tempFlag = tempstring != textBox_deviceID.Text; }));
                            if (tempFlag)
                            {
                                this.Invoke((EventHandler)(delegate { label_autoResult.Text = "擦除中。。。"; }));
                                outStr = processCmd("nrfjprog --eraseall" + DefinedParam.clockspeed);
                                if (outStr.error.Length == 0)
                                {
                                    this.Invoke((EventHandler)(delegate { tempFlag = File.Exists(textBox_fileName.Text); }));
                                    if (tempFlag == true)
                                    {
                                        this.Invoke((EventHandler)(delegate { label_autoResult.Text = "烧录中。。。"; }));
                                        outStr = processCmd("nrfjprog --program " + textBox_fileName.Text + " --verify" + DefinedParam.clockspeed);
                                        if (outStr.error.Length == 0)
                                        {
                                            outStr = processCmd("nrfjprog --rbp all" + DefinedParam.clockspeed);
                                            if (outStr.error.Length == 0)
                                            {
                                                outStr = processCmd("nrfjprog --reset" + DefinedParam.clockspeed);
                                                if (outStr.error.Length == 0)
                                                {
                                                    this.Invoke((EventHandler)(delegate
                                                    {
                                                        System.Media.SystemSounds.Beep.Play();
                                                        textBox_deviceID.Text = tempstring;
                                                        label_autoResult.Text = "烧录成功";
                                                        programSucessNum++;
                                                        label_sucessNum.Text = programSucessNum.ToString();
                                                    }));
                                                }
                                                else
                                                {
                                                    this.Invoke((EventHandler)(delegate { textBox_outLog.AppendText(outStr.error); }));
                                                }
                                            }
                                            else
                                            {
                                                this.Invoke((EventHandler)(delegate { textBox_outLog.AppendText(outStr.error); }));
                                            }
                                        }
                                        else
                                        {
                                            this.Invoke((EventHandler)(delegate { textBox_outLog.AppendText(outStr.error); }));
                                        }
                                    }
                                    else
                                    {
                                        this.Invoke((EventHandler)(delegate
                                        {
                                            MessageBox.Show(textBox_fileName.Text + "文件不存在");
                                            flagFileNotExists = false;
                                        }));
                                    }
                                }
                                else
                                {
                                    this.Invoke((EventHandler)(delegate { textBox_outLog.AppendText(outStr.error); }));
                                }
                            }
                            else
                            {
                                this.Invoke((EventHandler)(delegate { label_autoResult.Text = "已烧录，请更换主板"; }));
                            }
                        }
                    }
                    Thread.Sleep(3000);
                }
            }
            catch (Exception e)
            {

            }
        }

        private void Form_nRFTool_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.Exit();
        }

        private void button_clockspeed_Click(object sender, EventArgs e)
        {
            try
            {
                if (int.Parse(textBox_clockspeed.Text) < 125)
                {
                    label_autoResult.Text = "参数错误";
                    return;
                }
            }
            catch
            {
                label_autoResult.Text = "参数错误";
                return;
            }
            DefinedParam.clockspeed = " --clockspeed " + textBox_clockspeed.Text;
            label_autoResult.Text = "设置成功";
        }
    }

    class FlagClass
    {
        private static int flagAotuRun = 0;
        Object locker = new Object();

        public int get()
        {
            return flagAotuRun;
        }

        public void set(int flag)
        {
            lock (locker)
            {
                flagAotuRun = flag;
            }
        }
    }

    class CmdReturnStr
    {
        public string output;
        public string error;
    }

    public static class DefinedParam
    {
        public static string clockspeed = " --clockspeed 500";
    }
}
